﻿using ExpressesClass.BestApi.Utils.jsonUtil;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

namespace ExpressesClass.BestApi.Utils
{
    class JsonParser
    {

        public static string objToJson(object obj)
        {
            try
            {
                JSONWriter jsonWriter = new JSONWriter();
                return jsonWriter.write(obj);
            }
            catch
            {
                throw new Exception();
            }
        }

        public static T jsonToObj<T>(string jsonText)
        {

            JsonReader reader = new JSONValidatingReader(new ExceptionErrorListener());
            Object rootObj = reader.read(jsonText);
            if (rootObj == null)
            {
                return default(T);
            }
            Type type = typeof(T);
            if (typeof(IDictionary).IsAssignableFrom(rootObj.GetType()))
            {
                Dictionary<object, object> dictionary = (Dictionary<object, object>)rootObj;
                if (dictionary.Count == 1)
                {
                    foreach (object obj in dictionary.Keys)
                    {
                        if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
                        {
                            return (T)convertJson2Object(obj, type);
                        }
                    }
                }
            }
            return (T)convertJson2Object(rootObj, type);

        }

        private static object convertJson2Object(object rootObj, Type type)
        {
            object result = type.Assembly.CreateInstance(type.FullName);
            if (typeof(IDictionary).IsAssignableFrom(rootObj.GetType()))
            {
                Dictionary<object, object> dictionary = (Dictionary<object, object>)rootObj;

                foreach (object obj in dictionary.Keys)
                {
                    string itemName = obj.ToString();
                    Object itemValue = dictionary[itemName];

                    PropertyInfo[] properties = type.GetProperties();
                    if (!isContainProp(properties, itemName))
                    {
                        continue;
                    }
                    PropertyInfo info = getInfoByName(properties, itemName);

                    if (itemValue != null)
                    {
                        Type propType = info.PropertyType;
                        if (propType == typeof(string))
                        {
                            string value = itemValue.ToString();
                            if (!value.Contains("\""))
                            {
                                Console.WriteLine(itemName + "的数据类型传入错误，应为字符串类型");
                                Console.ReadKey();
                            }

                            info.SetValue(result, value.Substring(1), null);
                        }
                        else if (propType == typeof(int?))
                        {
                            int convert = Convert.ToInt32(itemValue);
                            info.SetValue(result, convert, null);
                        }
                        else if (propType == typeof(float?))
                        {
                            float convert = Convert.ToSingle(itemValue);
                            info.SetValue(result, convert, null);
                        }
                        else if (propType == typeof(long?))
                        {
                            long convert = Convert.ToInt64(itemValue);
                            info.SetValue(result, convert, null);
                        }
                        else if (propType == typeof(double?))
                        {
                            double convert = Convert.ToDouble(itemValue);
                            info.SetValue(result, convert, null);
                        }
                        else if (propType == typeof(bool))
                        {
                            if ("false".Equals(itemValue) || "true".Equals(itemValue))
                            {
                                bool convert = Convert.ToBoolean(itemValue);
                                info.SetValue(result, convert, null);
                            }
                            else
                            {
                                Console.WriteLine(itemName + "的数据类型传入错误，应为布尔类型");
                                Console.ReadKey();
                            }
                        }
                        else if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(List<>))
                        {
                            object list = convertList(itemValue, propType);
                            info.SetValue(result, list, null);
                        }
                        else
                        {
                            object objs = convertJson2Object(itemValue, propType);
                            info.SetValue(result, objs, null);
                        }
                    }
                }
            }

            return result;
        }

        private static object convertList(Object itemValue, Type propType)
        {
            object result = propType.Assembly.CreateInstance(propType.FullName);
            Type genericType = propType.GetGenericArguments()[0];
            MethodInfo methodinfo = propType.GetMethod("Add");



            if (typeof(ArrayList).IsAssignableFrom(itemValue.GetType()))
            {
                ArrayList al = (ArrayList)itemValue;

                if (genericType.IsValueType || genericType == typeof(string))
                {
                    foreach (object o in al)
                    {
                        methodinfo.Invoke(result, new object[] { o });
                    }
                }
                else
                {
                    foreach (object o in al)
                    {
                        methodinfo.Invoke(result, new object[] { convertJson2Object(o, genericType) });
                    }
                }

            }

            return result;

        }

        private static Boolean isContainProp(PropertyInfo[] fields, string nodeName)
        {

            if (fields == null || fields.Length < 0)
            {
                return false;
            }

            if (nodeName == null || "".Equals(nodeName))
            {
                return false;
            }

            foreach (PropertyInfo field in fields)
            {
                if (field.Name.Equals(nodeName))
                {
                    return true;
                }
            }
            return false;
        }

        private static PropertyInfo getInfoByName(PropertyInfo[] fields, string nodeName)
        {
            foreach (PropertyInfo field in fields)
            {
                if (field.Name.Equals(nodeName))
                {
                    return field;
                }
            }

            return null;
        }
    }
}
